--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   00:37:16 01/16/2010
-- Design Name:   
-- Module Name:   C:/Custom32Processor/MySOC/Test_Datapath.vhd
-- Project Name:  MySOC
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: Datapath
-- 
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes: 
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation 
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;

-- General package
use work.GeneralProperties.ALL;
 
ENTITY Test_Datapath IS
END Test_Datapath;
 
ARCHITECTURE behavior OF Test_Datapath IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Datapath
    Port ( InImediate          : in  STD_LOGIC_VECTOR ((bus_size - 6) downto 0);
	        InMemory            : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           InExternal          : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  OutExternal         : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  Flags               : out STD_LOGIC_VECTOR (3 downto 0);
			  SelMuxInput         : in  MultiplexSignals;
           SelAluOp            : in  ALU_operations;
			  SelShifterOp        : in  Shifter_operations;
			  RegFileWriteAddress : in  ProcessorRegisters;
			  RegFileReadAAddress : in  ProcessorRegisters;
			  RegFileReadBAddress : in  ProcessorRegisters;
			  RegFileReadAEnable  : in STD_LOGIC;
			  RegFileReadBEnable  : in STD_LOGIC;
			  WriteRegistersFile  : in STD_LOGIC;
			  RegisterAValue      : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  RegisterBValue      : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           OutputEnable        : in  STD_LOGIC
			  );
    END COMPONENT;
    

   --Inputs
   signal InImediate          : std_logic_vector((bus_size - 6) downto 0) := (others => '0');
	signal InMemory          : std_logic_vector((bus_size - 1) downto 0) := (others => '0');
   signal InExternal          : std_logic_vector((bus_size - 1) downto 0) := (others => '0');
   signal SelMuxInput         : MultiplexSignals := sel_External;
   signal SelAluOp            : ALU_operations := op_pass;
   signal SelShifterOp        : Shifter_operations := op_pass;
   signal RegFileWriteAddress : ProcessorRegisters := r0;
   signal RegFileReadAAddress : ProcessorRegisters := r0;
   signal RegFileReadBAddress : ProcessorRegisters := r0;
   signal RegFileReadAEnable  : std_logic := '0';
   signal RegFileReadBEnable  : std_logic := '0';
   signal WriteRegistersFile  : std_logic := '0';
   signal OutputEnable        : std_logic := '0';

 	--Outputs
   signal OutExternal : std_logic_vector((bus_size - 1) downto 0);
   signal Flags : std_logic_vector(3 downto 0);
	signal RegisterAValue : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
	signal RegisterBValue : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: Datapath PORT MAP (
          InImediate => InImediate,
			 InMemory => InMemory,
          InExternal => InExternal,
          OutExternal => OutExternal,
          Flags => Flags,
          SelMuxInput => SelMuxInput,
          SelAluOp => SelAluOp,
          SelShifterOp => SelShifterOp,
          RegFileWriteAddress => RegFileWriteAddress,
          RegFileReadAAddress => RegFileReadAAddress,
          RegFileReadBAddress => RegFileReadBAddress,
          RegFileReadAEnable => RegFileReadAEnable,
          RegFileReadBEnable => RegFileReadBEnable,
          WriteRegistersFile => WriteRegistersFile,
			 RegisterAValue => RegisterAValue, 
			 RegisterBValue => RegisterBValue, 
          OutputEnable => OutputEnable
        );
 
   -- In order to implement this test we're going to test all control words needed to implement the follwing algorithm
	-- 1           r1 = 5;
	-- 2           input r2;       // Consider the external input to be one, so this while will only run once
	--             while (r2 != 0)
	--             {
	-- 3             r1 = r1 + r2;
	-- 4             r2--;
	--             }
	-- 5           output r1;      // Output should be 6
	-- 6           output r2;      // Output should be 0
   
	-- Stimulus process
   stim_proc: process
   begin		
      -- Reset
		REPORT "Reset" SEVERITY WARNING;
		wait for 200 ns;	
		
		-- r1 = 5;
		REPORT "r1 = 5;" SEVERITY WARNING;
		InImediate <= conv_std_logic_vector(5, (bus_size - 5));
		SelMuxInput <= sel_Imediate;
		
		SelAluOp <= op_pass;
		SelShifterOp <= op_pass;
				
		RegFileWriteAddress <= r1;		
		
		WriteRegistersFile <= '0';
		wait for 20 ns;
		WriteRegistersFile <= '1';
		wait for 20 ns;
		WriteRegistersFile <= '0';
		
		
		RegFileReadAAddress <= r0;
		RegFileReadBAddress <= r0;
		RegFileReadAEnable <= '0';
		RegFileReadBEnable <= '0';
		
		OutputEnable <= '0';		
      wait for 200 ns;
				

      -- input r2;
		REPORT "input r2;" SEVERITY WARNING;
		InExternal <= conv_std_logic_vector(1, bus_size);
		SelMuxInput <= sel_External;
		
		SelAluOp <= op_pass;
		SelShifterOp <= op_pass;
		
		RegFileWriteAddress <= r2;
				
		WriteRegistersFile <= '0';
		wait for 20 ns;
		WriteRegistersFile <= '1';
		wait for 20 ns;
		WriteRegistersFile <= '0';		
		
		RegFileReadAAddress <= r0;
		RegFileReadBAddress <= r0;
		RegFileReadAEnable <= '0';
		RegFileReadBEnable <= '0';
		
		OutputEnable <= '0';		
      wait for 200 ns;		

      -- r1 = r1 + r2;
		REPORT "r1 = r1 + r2;" SEVERITY WARNING;				
		InExternal <= (others => 'Z');
		InImediate <= (others => 'Z');										
		SelMuxInput <= sel_AluOut;		
		
		RegFileReadAAddress <= r1;
		RegFileReadBAddress <= r2;
		RegFileReadAEnable <= '1';
		RegFileReadBEnable <= '1';
		--wait for 20 ns;  -- Wait for memory settling down													
		
		SelAluOp <= op_add;
		SelShifterOp <= op_pass;      
				
		
		RegFileWriteAddress <= r1;
				
		WriteRegistersFile <= '0';
		wait for 20 ns;
		WriteRegistersFile <= '1';
		wait for 20 ns;
		WriteRegistersFile <= '0';
		
		OutputEnable <= '0';		
      wait for 200 ns;		
		
		-- r2--;
		REPORT "r2--;" SEVERITY WARNING;
		InExternal <= (others => 'Z');
		InImediate <= (others => 'Z');
		SelMuxInput <= sel_AluOut;
		
		RegFileReadAAddress <= r2;
		RegFileReadBAddress <= r0;
		RegFileReadAEnable <= '1';
		RegFileReadBEnable <= '0';
		
		SelAluOp <= op_dec;
		SelShifterOp <= op_pass;
						
		RegFileWriteAddress <= r2;
		
		WriteRegistersFile <= '0';
		wait for 20 ns;
		WriteRegistersFile <= '1';
		wait for 20 ns;
		WriteRegistersFile <= '0';		      		
		
		OutputEnable <= '0';		
      wait for 200 ns;		
		
		-- output r1;
		REPORT "output r1;" SEVERITY WARNING;
		InExternal <= (others => 'Z');
		InImediate <= (others => 'Z');
		SelMuxInput <= sel_AluOut;
		
		RegFileReadAAddress <= r1;
		RegFileReadBAddress <= r0;
		RegFileReadAEnable <= '1';
		RegFileReadBEnable <= '0';
		
		SelAluOp <= op_pass;
		SelShifterOp <= op_pass;
						
		RegFileWriteAddress <= r0;
		WriteRegistersFile <= '0';		
		
		OutputEnable <= '1';		
      wait for 200 ns;		
		
		-- output r2;
		REPORT "output r2;" SEVERITY WARNING;
		InExternal <= (others => 'Z');
		InImediate <= (others => 'Z');
		SelMuxInput <= sel_AluOut;
		
		RegFileReadAAddress <= r2;
		RegFileReadBAddress <= r0;
		RegFileReadAEnable <= '1';
		RegFileReadBEnable <= '0';
		
		SelAluOp <= op_pass;
		SelShifterOp <= op_pass;
						
		RegFileWriteAddress <= r0;
		WriteRegistersFile <= '0';		
		
		OutputEnable <= '1';		
      wait for 200 ns;

      wait;
   end process;

END;
